package com.example.apple.ddhr_new.utils;

import android.annotation.SuppressLint;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import sun.misc.BASE64Decoder;

/**
 * AES 是一种可逆加密算法，对用户的敏感信息加密处理 对原始数据进行AES加密后，在进行Base64编码转化；
 */
@SuppressLint({ "TrulyRandom", "DefaultLocale" })
public class AESUtil {

	// 若选择非ECB模式，请输入密钥偏移量，选择默认的
	private static String ivParameter = "1234567890123456";

	private static AESUtil instance = null;

	private AESUtil() {

	}

	public static AESUtil getInstance() {
		if (instance == null)
			instance = new AESUtil();
		return instance;
	}

	/**
	 * 加密
	 * 
	 * @param sKey
	 *            加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式，key需要为16位。
	 * @param sSrc
	 *            需要加密的字符串
	 * @return
	 * @throws Exception
	 */
	// @SuppressLint("TrulyRandom")
	// public static String encryptCBCPKCS5PaddingBase64(String sKey, String
	// sSrc) throws Exception {
	// Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
	// byte[] raw = sKey.getBytes();
	// SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
	// IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());//
	// 使用CBC模式，需要一个向量iv，可增加加密算法的强度
	// cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
	// byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
	// return new BASE64Encoder().encode(encrypted);// 此处使用BASE64做转码。
	// }

	/**
	 * 解密
	 * 
	 * @param sKey
	 *            加密用的Key 可以用26个字母和数字组成 此处使用AES-128-CBC加密模式，key需要为16位。
	 * @param sSrc
	 *            需要解密的字符串
	 * @return
	 * @throws Exception
	 */
	public static String decryptCBCPKCS5PaddingBase64(String sKey, String sSrc)
			throws Exception {
		byte[] raw = sKey.getBytes("ASCII");
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
		IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
		cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
		byte[] encrypted1 = new BASE64Decoder().decodeBuffer(sSrc);// 先用base64解密
		byte[] original = cipher.doFinal(encrypted1);
		String originalString = new String(original, "utf-8");
		return originalString;
	}

	/**
	 * 加密 AES/ECB/PKCS5Padding 16进制
	 * 
	 * @param sKey
	 * @param sSrc
	 * @return
	 * @throws Exception
	 */
	public static String encryptECB(String sKey, String sSrc) throws Exception {
		if (sKey == null) {
			return null;
		}
		// 判断Key是否为16位
		if (sKey.length() != 16) {
			return null;
		}
		byte[] raw = sKey.getBytes("utf-8");
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");// "算法/模式/补码方式"
		cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
		byte[] encrypted = cipher.doFinal(sSrc.getBytes("utf-8"));
		return bytesToHexString(encrypted);
	}

	/**
	 * 描述：解密 创建时间：2016年11月8日 下午9:36:00
	 * 
	 * @param sKey
	 * @param sSrc
	 * @return
	 * @throws Exception
	 */
	public static String decryptECB(String sKey, String sSrc) throws Exception {
		// 判断Key是否正确
		if (sKey == null) {
			return null;
		}
		// 判断Key是否为16位
		if (sKey.length() != 16) {
			return null;
		}
		byte[] raw = sKey.getBytes("utf-8");
		SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
		Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
		cipher.init(Cipher.DECRYPT_MODE, skeySpec);
		byte[] encrypted1 = hexStringToBytes(sSrc);
		byte[] original = cipher.doFinal(encrypted1);
		String originalString = new String(original, "utf-8");
		return originalString;
	}

	/**
	 * byte[] 来转换成16进制字符串
	 * 
	 * @param src
	 * @return
	 */
	private static String bytesToHexString(byte[] src) {
		StringBuilder stringBuilder = new StringBuilder("");
		if (src == null || src.length <= 0) {
			return null;
		}
		for (int i = 0; i < src.length; i++) {
			int v = src[i] & 0xFF;
			String hv = Integer.toHexString(v);
			if (hv.length() < 2) {
				stringBuilder.append(0);
			}
			stringBuilder.append(hv);
		}
		return stringBuilder.toString();
	}

	/**
	 * 16进制转成 byte[]
	 * 
	 * @param hexString
	 * @return
	 */
	private static byte[] hexStringToBytes(String hexString) {
		if (hexString == null || hexString.equals("")) {
			return null;
		}
		hexString = hexString.toUpperCase();
		int length = hexString.length() / 2;
		char[] hexChars = hexString.toCharArray();
		byte[] d = new byte[length];
		for (int i = 0; i < length; i++) {
			int pos = i * 2;
			d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
		}
		return d;
	}

	private static byte charToByte(char c) {
		return (byte) "0123456789ABCDEF".indexOf(c);
	}
}